﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Input;
using Windows.UI.Xaml;

namespace VivendoByteToolkit.Helpers
{
    public class WheelCommandHelper
    {
        #region Up
        public static ICommand GetUp(DependencyObject obj)
        {
            return (ICommand)obj.GetValue(UpProperty);
        }

        public static void SetUp(DependencyObject obj, ICommand value)
        {
            obj.SetValue(UpProperty, value);
        }

        public static readonly DependencyProperty UpProperty =
            DependencyProperty.RegisterAttached("Up",
            typeof(ICommand),
            typeof(WheelCommandHelper),
            new PropertyMetadata(null,
            new PropertyChangedCallback(Setup))); 
        #endregion

        #region Down
        public static ICommand GetDown(DependencyObject obj)
        {
            return (ICommand)obj.GetValue(DownProperty);
        }

        public static void SetDown(DependencyObject obj, ICommand value)
        {
            obj.SetValue(DownProperty, value);
        }

        public static readonly DependencyProperty DownProperty =
            DependencyProperty.RegisterAttached("Down",
            typeof(ICommand),
            typeof(WheelCommandHelper),
            new PropertyMetadata(null,
            new PropertyChangedCallback(Setup))); 
        #endregion

        #region Attached (to avoid to subscribe the event 'ManipulationCompleted' multiple times
        public static bool GetAttached(DependencyObject obj)
        {
            return (bool)obj.GetValue(AttachedProperty);
        }

        public static void SetAttached(DependencyObject obj,
            bool value)
        {
            obj.SetValue(AttachedProperty, value);
        }

        private static readonly DependencyProperty AttachedProperty =
            DependencyProperty.RegisterAttached("Attached",
            typeof(bool),
            typeof(FrameworkElement),
            new PropertyMetadata(false));
        #endregion

        private static void Setup(DependencyObject obj,
            DependencyPropertyChangedEventArgs e)
        {
            FrameworkElement ctl = obj as FrameworkElement;

            if (ctl != null)
            {
                ICommand oldValue = (ICommand)e.OldValue;
                ICommand newValue = (ICommand)e.NewValue;

                if (oldValue == null && newValue != null)
                {
                    if (GetAttached(ctl) == false)
                    {
                        SetAttached(ctl, true);
                        ctl.PointerWheelChanged += ctl_PointerWheelChanged;
                    }
                }
                else if (oldValue != null && newValue == null)
                {
                    ctl.SetValue(AttachedProperty, false);
                    ctl.PointerWheelChanged -= ctl_PointerWheelChanged;
                }
            }
        }

        static void ctl_PointerWheelChanged(object sender, Windows.UI.Xaml.Input.PointerRoutedEventArgs e)
        {
            var element = sender as FrameworkElement;
            ICommand command = null;

            var delta = e.GetCurrentPoint(null).Properties.MouseWheelDelta;

            if (delta < 0)
            {
                command = GetDown(element);
            }
            else
            {
                command = GetUp(element);
            }

            if (command != null)
            {
                if (command.CanExecute(null))
                {
                    command.Execute(null);
                }
            }
        }
    }
}